﻿using Microsoft.AspNetCore.Mvc;

namespace Gantt.Server.Service;

/// <summary>
/// 
/// </summary>
[ApiExplorerSettings(GroupName = "Gantt")]
public partial class GanttService : IApplicationService
{
    private readonly SugarRepository<GanttTasks> _thisRepository;
    private readonly ICurrentUser _currentUser;

    public GanttService(SugarRepository<GanttTasks> thisRepository, ICurrentUser currentUser)
    {
        _thisRepository = thisRepository;
        _currentUser = currentUser;
    }

    public async Task<RestfulResult<List<TasksModel>>> GetPagesAsync(TasksPageParam data)
    {
        var restful = new RestfulResult<List<TasksModel>> { Code = CodeStatus.OK };
        if (data == null || data.ProjectId <= 0) return restful;
        DateTime beginTime = data.BeginTime ?? DateTime.Now.AddDays(-25);
        DateTime endTime = data.EndTime ?? DateTime.Now.AddDays(5);

        var query = await _thisRepository.AsQueryable()
                .Where((a) => a.ProjectId == data.ProjectId && a.Creator == _currentUser.UserId)
                .InnerJoin<GanttType>((a, b) => a.TypeId == b.Id)
                .InnerJoin<GanttStatus>((a, b, c) => a.StatusId == c.Id)
                .InnerJoin<GanttLevel>((a, b, c, d) => a.LevelId == d.Id)
                .OrderBy((a, b, c, d) => a.Start)
                .Select((a, b, c, d) => new TasksModel
                {
                    ProjectId = a.ProjectId,
                    id = a.Id,
                    label = a.Label,
                    collapsed = a.Collapsed == 1,
                    dependentOns = a.DependentOn,
                    end = a.End,
                    start = a.Start,
                    parentId = a.ParentId,
                    duration = a.Duration,
                    percent = a.Percent,
                    progress = a.Progress,
                    typeId = b.Id,
                    type = b.Code,
                    user = a.User,
                    Color = b.Color,
                    StatusId = c.Id,
                    StatusName = c.Name,
                    StatusColor = c.Color,
                    LevelId = d.Id,
                    LevelName = d.Name,
                    LevelColor = d.Color,
                    DurationDays = (a.End - a.Start).Days + 1
                }).ToListAsync();

        restful.Data = query;
        return restful;
    }

    public async Task<RestfulResult<List<ProjectDto>>> GetTasksListAsync(long id)
    {
        var restful = new RestfulResult<List<ProjectDto>>() { Code = CodeStatus.OK };
        if (id <= 0) return restful;

        var query = await _thisRepository.AsQueryable()
            .Where((a) => a.ProjectId == id && a.Creator == _currentUser.UserId)
             .OrderBy(u => u.CreateTime)
             .Select(u => new ProjectDto
             {
                 Id = u.Id,
                 Name = u.Label
             })
            .ToListAsync();

        restful.Data = query;
        return restful;
    }

    public async Task<RestfulResult<PageResult<ProjectDto>>> GetTypeListAsync()
    {
        var restful = new RestfulResult<PageResult<ProjectDto>>() { Code = CodeStatus.OK };
        PageParam data = new PageParam { PageNo = 1, PageSize = 100 };

        var query = await _thisRepository.Change<GanttType>().AsQueryable()
            .Where(u => u.IsDisable == 0)
             .OrderBy(u => u.Sort)
             .Select(u => new ProjectDto
             {
                 Id = u.Id,
                 Code = u.Code,
                 Name = u.Name
             })
            .ToPageAsync(data.PageNo, data.PageSize);

        restful.Data = query;
        return restful;
    }

    public async Task<RestfulResult<PageResult<StatusDto>>> GetStatusListAsync()
    {
        var restful = new RestfulResult<PageResult<StatusDto>>() { Code = CodeStatus.OK };
        PageParam data = new PageParam { PageNo = 1, PageSize = 100 };

        var query = await _thisRepository.Change<GanttStatus>().AsQueryable()
             .OrderBy(u => u.Sort)
             .Select(u => new StatusDto
             {
                 Id = u.Id,
                 Color = u.Color,
                 Name = u.Name
             })
            .ToPageAsync(data.PageNo, data.PageSize);

        restful.Data = query;
        return restful;
    }

    public async Task<RestfulResult<PageResult<StatusDto>>> GetLevelListAsync()
    {
        var restful = new RestfulResult<PageResult<StatusDto>>() { Code = CodeStatus.OK };
        PageParam data = new PageParam { PageNo = 1, PageSize = 100 };

        var query = await _thisRepository.Change<GanttLevel>().AsQueryable()
             .OrderBy(u => u.Sort)
             .Select(u => new StatusDto
             {
                 Id = u.Id,
                 Color = u.Color,
                 Name = u.Name
             })
            .ToPageAsync(data.PageNo, data.PageSize);

        restful.Data = query;
        return restful;
    }

    public async Task<RestfulResult> SubmitAsync(TasksInputDto data)
    {
        RestfulResult restful = new() { Code = CodeStatus.BadRequest };
        if (data == null) return restful;
        if (data.label.IsNullOrWhiteSpace()) { restful.Message = "任务名称不能为空"; return restful; }
        if (data.typeId <= 0) { restful.Message = "请选择类别"; return restful; }
        if (data.StatusId <= 0) { restful.Message = "请选择状态"; return restful; }
        if (data.LevelId <= 0) { restful.Message = "请选择优先级"; return restful; }

        if (data.id > 0)
        {
            if (data.id == data.parentId) { restful.Message = "上级节点不能是自身节点"; return restful; }
            if (data.id == data.dependentOns) { restful.Message = "紧前节点不能是自身节点"; return restful; }
        }

        GanttTasks resultData = new()
        {
            ProjectId = data.ProjectId,
            Id = data.id,
            Label = data.label,
            User = data.user,
            ParentId = data.parentId,
            Start = data.Start,
            End = data.End,
            Percent = data.percent,
            TypeId = data.typeId,
            DependentOn = data.dependentOns,
            StatusId = data.StatusId,
            LevelId = data.LevelId,
        };
        resultData.Start = new DateTime(data.Start.Year, data.Start.Month, data.Start.Day, 0, 0, 0);
        resultData.End = new DateTime(data.End.Year, data.End.Month, data.End.Day, 23, 59, 59);
        resultData.Duration = (long)(data.End - data.Start).TotalMilliseconds;

        if (data.id == 0)
        {
            bool result = await _thisRepository.InsertAsync(resultData);
            if (result)
            {
                restful.Data = result;
                restful.Code = CodeStatus.OK;
                return restful;
            }
            restful.Message = "添加失败";
            return restful;
        }
        else
        {
            if (data.StatusId == 3)
                resultData.Progress = resultData.Percent = 100;

            GanttTasks oneData = _thisRepository.GetFirst(x => x.Id == data.id);
            oneData.ProjectId = resultData.ProjectId;
            oneData.Id = resultData.Id;
            oneData.Label = resultData.Label;
            oneData.User = resultData.User;
            oneData.ParentId = resultData.ParentId;
            oneData.Start = resultData.Start;
            oneData.End = resultData.End;
            oneData.Percent = resultData.Percent;
            oneData.TypeId = resultData.TypeId;
            oneData.DependentOn = resultData.DependentOn;
            oneData.StatusId = resultData.StatusId;
            oneData.LevelId = resultData.LevelId;
            oneData.Progress = resultData.Progress;

            bool result = await _thisRepository.UpdateAsync(oneData, false);
            if (result)
            {
                restful.Data = result;
                restful.Code = CodeStatus.OK;
                return restful;
            }
            restful.Message = "修改失败";
            return restful;
        }
    }

    public async Task<RestfulResult> DeleteAsync(long id)
    {
        RestfulResult restful = new() { Code = CodeStatus.BadRequest };

        if (id == 0)
        {
            restful.Message = "删除失败";
            return restful;
        }
        bool isDelete = await _thisRepository.DeleteByIdAsync(id);
        if (isDelete)
        {
            restful.Data = isDelete;
            restful.Message = "删除成功";
            restful.Code = CodeStatus.OK;
            return restful;
        }
        restful.Data = isDelete;
        restful.Message = "删除失败";
        return restful;
    }
}
 